(function($){    
	var defaultConfig = {
            theme : '',
            textFormat : 'item["text"]',
            stringItemTmp : '',
            valueField : 'value',
            direction : 'h',
            disabled : false,
            selectable : true,
            root : 'items'
	    },
	    /**
	     * 字符串项的模板.
	     */
        stringListItemTmp = [
			'<% for ( var i = 0; i < items.length; i++ ) { var item = items[i]; %>',
				'<div class="stringListItem <%= item["disabled"] === true ? "disabled" : "" %>" val="<%= item[valueField] || item["id"]%>" >',
					'<span initMode="<%= item["editMode"] || "view" %>" class="stringListItemText">{0}</span>',
					'<% if(item["deletable"] !== false ){ %>',
					   '<span class="d">×</span>',
					'<% } %>',
				'</div>',
			'<% } %>'
		].join(''),		
		/**
		 * 注册即时编辑功能.
		 */
		regEditInplace = function($stringItem){
		    var _this = this,
                $editorPane = $stringItem.find('.stringListItemText'); 	
                	    
            $editorPane.editInplace({
                mode : $editorPane.attr('initMode'),
                editorCls : 'stringListItemEditor',
                isEmptyRemove : true,
                onSave : function(newText, originalText) {     
                    var $editor = this;               
                    var val = $editor.parent().attr('val');
                    if(!val){
                        if(_this.config['addUrl']){
                            $.ajax({
                                type : 'POST',
                                url : tmpl( _this.config['addUrl'], { text : window.encodeURIComponent( newText ) } ),
                                success : ujs.hr( function( msg ){
                                    $editor.unbind('dblclick');
                                })
                            });
                        } else {
                            $editor.unbind('dblclick');
                        }
                        if(!newText){
                            _this.fire('remove', originalText, $editor.parent());
                            $stringItem.remove();  
                        } else {
                            _this.fire('add', newText, originalText, $editor.parent());
                        }
                    } else {
                        _this.fire('update', newText, originalText, $editor.parent());
                    }
                }
            });
		};
		
	//--------------------------------------------------------------------------------------------------------------------
	
	/**
	 * @class StringList
	 * @constructor
	 * @param config {Options}
	 */
	function StringList(config){
	    var _this = this;	    
	    Observable.enable(this);	    
	    //配置处理.
		this.config = $.extend({}, defaultConfig, config);
		if(!this.config['renderTo']){
			return;
		}
		//$wrapper
        this.$wrapper = $(this.config['renderTo']);
        this.$wrapper.addClass('stringList');
        if(this.config['type'] === 'radiobox' && !_this.config['theme']){
            _this.config['theme'] += ' radioGroup';
        }
        if(_this.config['theme']){
            _this.$wrapper.addClass(_this.config['theme']);
        }
        //$addBtn
        if(_this.config['addable'] !== false){
            _this.$addBtn = $('<div class="addBtn">+</div>').appendTo(_this.$wrapper);
        }
        //初始禁用状态.        
		if(this.config['disabled'] === true){
            this.disable();
		}
		//初始化展示方向.
		if(this.config['direction'] === 'v'){
		    this.setDirection('v');
		}
        //初始值兼容处理.
        if(_this.config['value'] && !_this.config['values']){
            _this.config['values'] = [_this.config['value']];
        }	
        //事件预定义.
        _this.on(_this.config['events']);	
		//单击选择.
        _this.$wrapper.undelegate('click').delegate('.stringListItem:not(.last)', 'click', function() {
            if(_this.config['selectable'] === false){                
                return false;
            }            
            var $stringItem = $(this);
            if(_this.config['isDisabled'] === true || $stringItem.hasClass('disabled')){                
                return false;
            }
            if(_this.config['type'] === 'radiobox'){
                //若控件作为单选按钮组使用，先清除已选项，再选中当前项。
                _this.clearCheckState();
                $stringItem.addClass('selected');                   
            } else {
                $stringItem.toggleClass('selected');             
            }            
            //触发onClick事件, onClick(val, isSelected, $stringItem)。
            if(Type.isFunction(_this.config['onClick'])){
                _this.config['onClick'].call(_this, $stringItem.attr('val'), $stringItem.hasClass('selected'), $stringItem);
            }
        })
        //删除项.
        .delegate('.stringListItem .d', 'click', function(e) {
            //避免点击删除按钮时，选中当前项。
            e.stopPropagation();
            var $delBtn = $(this),
                delActionFun = function(){
                    if(_this.config['delUrl']){
                        //异步删除.
                        $.ajax({
                            type : _this.config['delAjaxType'] || 'get',
                            url : tmpl(_this.config['delUrl'], {
                                val : $delBtn.parent().attr('val'), 
                                text : $delBtn.prev().text() 
                            }),
                            success : ujs.hr(function(){
                                $delBtn.parent().remove();
                                _this.fire('remove');
                            })
                        });
                    } else {
                        _this.fire('remove', $delBtn.parent().attr('val'));
                        $delBtn.parent().remove();
                    }    
                };
               
            if(_this.config['isDeletingConfirm'] !== false){             
                bubble.confirm(_this.config['isDeletingConfirmText'] || 'Delete?', function(){                    
                    delActionFun.call(_this);                
                });
            } else {
                delActionFun.call(_this);
            }
        })        
        //添加功能.
        .delegate('.addBtn', 'click', function(e) {     
            _this.fire('clickAddTrigger');       
            var $editingItem = $(this).prev().find('.editInplace.editing');
            if( $editingItem.isEmpty() ){                                        
                _this.addItem({ 
                    text : '', 
                    value : String.newGuid(),
                    editMode : 'edit' 
                });                        
            } else {
                $editingItem.find('input').focus();
            }
            return false;
        });		
		//初始化数据.
		if(this.config['isInitData'] !== false){		    		
            this.refresh();	
		} else {
		    this.isInitData = false;
		}			
	}
	
	//--------------------------------------------------------------------------------------------------------------------
	
	/**
	 * 
	 */
	StringList.prototype.setMode = function(mode){
	    if(mode == 'edit'){
	        this.newItem();
	    }
	};
	
	StringList.prototype.newItem = function(){        
        if(this.$addBtn){
            this.$addBtn.trigger('click');
        }        
    };
	
	//--------------------------------------------------------------------------------------------------------------------
	
	StringList.prototype.refresh = function(){	
    	
    	this.isInitData = true;
    	
		var _this = this,
		    originalValues = _this.getValues();
			
		var	handler = function(msg){
		    msg['items'] = msg[_this.config['root']];            
            _this._rawData = msg['items'];            
            if(_this.config['stringFilter']){
                msg['items'] = $.grep( msg['items'], _this.config['stringFilter'] );
            }    
            _this.clearItems();            
            if(msg['items']){
                _this.addItem(msg['items']);
            }            
            if(_this.config['deletable'] === false){
                _this.$wrapper.find('.d').remove();
            }            
            //默认值.
            if(originalValues && originalValues.length){
                _this.setValues(originalValues);
            } else if(_this.config['values']){
                _this.setValues(_this.config['values']);
            }            
            //过滤items.
            if(_this.config['filter']){
                _this.filter(_this.config['filter']);
            }
        };
				    	
    	if( _this.config['initUrl'] ){		    	
    		$.ajax({
    			url : _this.config['initUrl'],
    			success : ujs.hr(handler)
    		});
		} else {
		    var dataconfig = _this.config['data']; 
		    var emptyData = { items : [] };		
		    
		    //data:'Destruct|allowDestruct,Location|allowLocation,User Info|allowParticipant,Broadcast|allowBroadcast,Allow Delete|allowDelete'		    
		    if(Type.isString(dataconfig)){
		        var dataArr = dataconfig.split(',');		        
		        for(var j=0; j<dataArr.length; j++){
		            var dataItemArr = dataArr[j].split('|');
		            emptyData.items.push({
		                text : dataItemArr[0],
		                value : dataItemArr[1]
		            });
		        }
		        _this.config['data'] = emptyData;
		    } else if(Type.isEmpty(dataconfig)) {
		        _this.config['data'] = emptyData;
		    }
		    
            handler(_this.config['data']);             
		}
	};
	
	//--------------------------------------------------------------------------------------------------------------------
	
	StringList.prototype.addItem = function(items, cb){
	    var _this = this;
	    if(!(items instanceof Array)){
	        items = [ items ];
	    }
	    var $newItems = $(tmpl(
	        stringListItemTmp.format(
	            this.config['stringItemTmp'] || ( '<%=' + this.config['textFormat'] + '%>' )
            ), 
	        { 
	            items : items, 
	            valueField : this.config['valueField'] 
            } 
        ));
        
        if(this.config['addable'] === false){
            this.$wrapper.append($newItems);    
        } else {
            this.$addBtn.before($newItems);
        }   
        
        if(this.config['addable']){
            (function(){
                $newItems.each(function(){
                    regEditInplace.call(_this, $(this));    
                });    
            }).defer(0);
        }        
        if(cb){
            cb.call(this, $newItems);
        }                  
        return this;    
	};
	
	StringList.prototype.clearItems = function(){
	    this.$wrapper.find('.stringListItem').remove();
	    return this;
	};
	
	//-------------------------------------------------------------------------------------------------
	
	/**
	 * 获取选中的值.
	 */
	StringList.prototype.getValues = function(mapFun){
	    var _this = this,
		    ids = this.$wrapper.find('.stringListItem.selected').map(function(){
    			return $(this).attr('val');
    		}).get();
    				
		if(Type.isFunction(mapFun)){
    		return $.map(ids, function(id){
    		    return mapFun(id, _this._rawData); 
    		});
		} else {
		    return ids;
		}
	};
	
	/**
	 * 获取所有的值, 不管是否被选中.
	 */
	StringList.prototype.getAllValues = function(){
        var _this = this,
            ids = this.$wrapper.find('.stringListItem').map(function(){
                return $(this).attr('val');
            }).get();
                    
        return ids;
    };
	
	/**
     * 获取值.
     */
    StringList.prototype.getValue = function(){
        return this.getValues()[0];
    };
	
	/**
	 * 获取指定的选项.
	 * @param condition {Function|Array|String} 过滤函数|ID数组|单独ID.
	 * @return Object.
	 */
    StringList.prototype.getOptions = function(condition){     
        condition = condition || function(){return true;};   
        if(Type.isString(condition)){
            var stringItemID = condition;
            return this.getOptions([stringItemID]);
        }
        if(Type.isArray(condition)){
            var stringItemIdArr = condition;
            condition = function($strItem){
                return stringItemIdArr.contains($strItem.attr('val'));
            };    
        }
        return this.$wrapper.find('.stringListItem').map(function(){
            var $strItem = $(this),
                $strItemText = $strItem.find('.stringListItemText');            
            if(condition($strItem)){
                return {
                    text : $strItemText.hasClass('editing') ? '' : $strItemText.text(),
                    value : $strItem.attr('val') 
                };
            }
        }).get();
    };
    
    /**
     * 
     */
    StringList.prototype.getOptionByValue = function(val){        
        return this.$wrapper.find('.stringListItem').map(function(){
            var $strItem = $(this),
                $strItemText = $strItem.find('.stringListItemText'),
                itemValue = $strItem.attr('val');
            if(itemValue === val){
                return {
                    text : $strItemText.hasClass('editing') ? '' : $strItemText.text(),
                    value : itemValue 
                };
            }
        });
    };
    
    //-------------------------------------------------------------------------------------------------
    
    /**
     * 获取选中状态, 如:
     * {
     *     str : true,
     *     str2 : false
     * }
     */
    StringList.prototype.getCheckState = function(){
        var _this = this, state = {};
        
        this.$wrapper.find('.stringListItem').map(function(){
            var $strItem = $(this), value = $strItem.attr('val');            
            state[value] = $strItem.is('.selected:visible');             
            return state;
        });
                    
        return state;
    };
    
    /**
     * 设置选中状态
     */
    StringList.prototype.setCheckState = function(state){
        if(Type.isObject(state)){
            this.$wrapper.find('.stringListItem').map(function(){
                var $strItem = $(this), value = $strItem.attr('val');                            
                if(state[value] === true){
                    $strItem.addClass('selected');
                } else {
                    $strItem.removeClass('selected');
                }
            });
        }        
    };    
    
    /**
     * 清除选中状态.
     * @method clearCheckState
     */
    StringList.prototype.clearCheckState = function(state){
        this.setCheckState({});
    };
    
    //-------------------------------------------------------------------------------------------------
    
    StringList.prototype.getDirection = function(){
        return this.config['direction'];
    };
    
    StringList.prototype.setDirection = function(direction){
        if(direction && direction.toLowerCase() === 'v'){    
            this.config['direction'] = 'v';
            this.$wrapper.addClass('vertical');        
        } else {
            this.config['direction'] = 'h';
            this.$wrapper.removeClass('vertical');
        }                
    };
    
    //-------------------------------------------------------------------------------------------------
    
    StringList.prototype.setValue = function(str){        
        return this.setValues([str]);                
    };
    
	StringList.prototype.setValues = function(strsArr){	    
		strsArr = strsArr || [];
		this.clearSelected();
		this.$wrapper.find('.stringListItem').each(function(){
			if(strsArr.contains($(this).attr('val'))){
				$(this).addClass('selected');
			}
		});
		
		if(strsArr.length === 1 && this.config['onClick']){
		    this.config['onClick'].call(this, strsArr[0], true);
		}
		return this;		
	};
	
	//-------------------------------------------------------------------------------------------------
	
	StringList.prototype.clearSelected = function(){
		this.$wrapper.find('.stringListItem.selected').removeClass('selected');
		return this;
	};
	
	/**
	 * 重置(会应用默认值).
	 */
	StringList.prototype.reset = function(){	    
	    if(this.config['filter']){
	        this.filter(this.config['filter']);
	    } else {
	        this.showAllItems();
	    }
	    
	    if(this.config['values']){
	        this.setValues(this.config['values']);
	    } else {
	        this.clearSelected();
	    }
	    return this;
	};
	
	/**
	 * 过滤显示(隐藏)StringItems.
     * @param {Array} strsArr
     * @param {Boolean} isHidden : 判断是否过滤隐藏，默认为false.
	 */
	StringList.prototype.filter = function(strsArr, isHidden){	    
	    var $stringItems = this.$wrapper.find('.stringListItem');
	    $stringItems.each(function(){
	        var $stringItem = $(this),
	            str = $stringItem.attr('val');
	            actions = ['show', 'hide'];
	        if(isHidden === true){
	            actions = actions.reverse();
	        }
	        $stringItem[ actions[ strsArr.contains(str) ? 0 : 1 ] ]();
	    });
	    return this;
	};
	
	/**
	 * 显示所有项.
	 */
	StringList.prototype.showAllItems = function(){        
        var $stringItems = this.$wrapper.find('.stringListItem');
        $stringItems.each(function(){
            $(this).show();
        });
        return this;
    };
    
    //-----------------------------------------------------------------------------------
	
	/**
	 * 禁用所有选项.
	 * @method disable
	 * return this
	 */
	StringList.prototype.disable = function(){
	    this.config['isDisabled'] = true;
	    this.$wrapper.addClass('disabled');
	    return this;
	};
	
	/**
	 * 全局启用选项.
	 * @method enable
	 * @return this
	 */
	StringList.prototype.enable = function(){
        this.config['isDisabled'] = false;
        this.$wrapper.removeClass('disabled');
        return this;
    };
    
    /**
     * 判断字符串列表是否已被禁用.
     * @method isDisabled
     * @return this
     */
    StringList.prototype.isDisabled = function(){
        return !!this.config['isDisabled'];
    };
    
    //-----------------------------------------------------------------------------------
    
    /**
     * 切换为只读状态.
     * @method readonly
     * @return this
     */
    StringList.prototype.readonly = function(){
        this.$wrapper.find('.stringListItem').addClass('readonly');
        return this;    
    };
    
    /**
     * 切换为编辑状态.
     * @method editable
     * @return this 
     */
    StringList.prototype.editable = function(){
        this.$wrapper.find('.stringListItem').removeClass('readonly');
        return this;    
    };
    
    //-----------------------------------------------------------------------------------
	
	/**
     * 注册为jQuery插件. 
     * @param {Option} config
     * @return jQuery
     */
    $.fn.stringList = function(config){        
        this.each(function(){   
            var stringListObj = new StringList($.extend({}, config, { renderTo : this }));         
            $(this).data('stringList', stringListObj).data('formField', stringListObj);                       
        });
        return this;
    };      	
})($);